package com.liuya.safe.policy.handler;

import com.liuya.common.exception.EntityExistException;
import com.liuya.common.ReflectUtil;
import com.liuya.common.StringUtil;
import com.liuya.db.sql.xml.Column;
import com.liuya.db.sql.xml.ContextValue;
import com.liuya.db.sql.xml.Parameter;
import com.liuya.db.sql.xml.Query;
import com.liuya.db.sql.xml.QueryType;
import com.liuya.db.sql.xml.RawSQL;
import com.liuya.db.sql.xml.Select;
import com.liuya.db.sql.xml.UserValue;
import com.liuya.safe.policy.service.QueryManagerService;

//@Component("queryRawHandler")
public class QueryRawHandler implements java.io.Serializable{

    private final QueryType query;
    private String[][] mappingClassPropertyAndTypes;

    public QueryRawHandler(QueryType xmlQuery) {
        this.query = xmlQuery;

        String mappingClass = query.getRawSQL().getSelect().getMappingClass();
        if (!StringUtil.isEmpty(mappingClass)) {
            mappingClassPropertyAndTypes = ReflectUtil.reflectJavaBean(mappingClass);
        }
    }

    public QueryType getQuery() {
        return query;
    }

    public String[] format(Parameter param) {
        Object value = param.getChoiceValue();
        if (value instanceof ContextValue) {
            return new String[] { "Context value", param.getContextValue().getKey() };
        } else if (value instanceof UserValue) {
            return new String[] { "User value", param.getUserValue().getKey() };
        }
        return null;
    }

    public Parameter getParameter(int index) {
        return query.getRawSQL().getParameter(index);
    }

    public void addParameter(String type, String key) {
        Parameter param = new Parameter();

        if ("userValue".equals(type)) {
            UserValue value = new UserValue();
            value.setKey(key);

            param.setContextValue(null);
            param.setUserValue(value);
        } else if ("contextValue".equals(type)) {
            ContextValue value = new ContextValue();
            value.setKey(key);

            param.setUserValue(null);
            param.setContextValue(value);
        }

        query.getRawSQL().addParameter(param);
    }

    /**
     * 更新参数
     * @param index
     * @param type
     * @param key
     */
    public void updateParameter(int index, String type, String key) {
        com.liuya.db.sql.xml.RawSQL rsql = query.getRawSQL();
        Parameter param = rsql.getParameter(index);

        if ("userValue".equals(type)) {
            UserValue value = new UserValue();
            value.setKey(key);

            param.setContextValue(null);
            param.setUserValue(value);
        } else if ("contextValue".equals(type)) {
            ContextValue value = new ContextValue();
            value.setKey(key);

            param.setUserValue(null);
            param.setContextValue(value);
        }
    }

    public void deleteParameter(int index) {
        query.getRawSQL().removeParameterAt(index);
    }

    public void moveParameter(String direct, int index) {
        RawSQL rawSql = query.getRawSQL();
        Parameter[] parameters = rawSql.getParameter();
        int moveIndex = index;

        // change parameter with it
        int changeIndex = -1;
        if ("top".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = 0;
            }
        } else if ("up".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = moveIndex - 1;
            }
        } else if ("down".equals(direct)) {
            if (moveIndex != (parameters.length - 1)) {
                changeIndex = moveIndex + 1;
            }
        } else if ("bottom".equals(direct)) {
            if (moveIndex != (parameters.length - 1)) {
                changeIndex = parameters.length - 1;
            }
        }

        if (changeIndex != -1) {
            Parameter moveCol = parameters[moveIndex];

            if ("top".equals(direct)) {
                rawSql.removeParameterAt(moveIndex);
                rawSql.addParameter(0, moveCol);
            } else if ("bottom".equals(direct)) {
                rawSql.removeParameterAt(moveIndex);
                rawSql.addParameter(rawSql.getParameterCount(), moveCol);
            } else if ("up".equals(direct) || "down".equals(direct)) {
                Parameter changeCol = parameters[changeIndex];

                rawSql.setParameter(changeIndex, moveCol);
                rawSql.setParameter(moveIndex, changeCol);
            }
        }
    }

    public Column getColumn(int index) {
        return query.getRawSQL().getSelect().getColumn(index);
    }

    public void addProperty(String columnName, String javaProp, String javaType, boolean readOnly) {
        Column column = new Column();
        column.setName(columnName);
        column.setTableAlias("");
        column.setProperty(javaProp);
        column.setJavaType(javaType);
        column.setReadOnly(readOnly);

        query.getRawSQL().getSelect().addColumn(column);
    }

    public void updateProperty(int index, String columnName, String javaProp, String javaType, boolean readOnly) {
        Column column = query.getRawSQL().getSelect().getColumn(index);
        column.setName(columnName);
        column.setTableAlias("");
        column.setProperty(javaProp);
        column.setJavaType(javaType);
        column.setReadOnly(readOnly);
    }

    public void deleteProperty(int index) {
        query.getRawSQL().getSelect().removeColumnAt(index);
    }

    public void moveProperty(String direct, int index) {
        Select select = query.getRawSQL().getSelect();
        Column[] columns = select.getColumn();
        int moveIndex = index;

        // change parameter with it
        int changeIndex = -1;
        if ("top".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = 0;
            }
        } else if ("up".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = moveIndex - 1;
            }
        } else if ("down".equals(direct)) {
            if (moveIndex != (columns.length - 1)) {
                changeIndex = moveIndex + 1;
            }
        } else if ("bottom".equals(direct)) {
            if (moveIndex != (columns.length - 1)) {
                changeIndex = columns.length - 1;
            }
        }

        if (changeIndex != -1) {
            Column moveCol = columns[moveIndex];

            if ("top".equals(direct)) {
                select.removeColumnAt(moveIndex);
                select.addColumn(0, moveCol);
            } else if ("bottom".equals(direct)) {
                select.removeColumnAt(moveIndex);
                select.addColumn(select.getColumnCount(), moveCol);
            } else if ("up".equals(direct) || "down".equals(direct)) {
                Column changeCol = columns[changeIndex];

                select.setColumn(changeIndex, moveCol);
                select.setColumn(moveIndex, changeCol);
            }
        }
    }

    public void setMappingClass(String mappingClass) {
        // update query
        query.getRawSQL().getSelect().setMappingClass(mappingClass);
        mappingClassPropertyAndTypes = ReflectUtil.reflectJavaBean(mappingClass);

        // clear mapping
        // Column[] columns=query.getRawSQL().getSelect().getColumn();
        // for( int i=0; i<columns.length; i++ ) {
        // Column column=columns[i];
        // column.setJavaType( null );
        // column.setProperty( null );
        // }
    }

    public String[][] getMappingClassPropertyAndTypes() {
        return mappingClassPropertyAndTypes;
    }

    public void setRawSql(String rawSql) {
        query.getRawSQL().setContent(rawSql);
    }

    public void save(String id, QueryManagerService queryManager) throws EntityExistException {
        queryManager.updateQuery(id, (Query) query);
    }

    public String getManagePage() {
        return "";
    }
}
